var util = require("./util"), Base = require("./base"), validApiKeys = [ "api", "success", "time", "code", "msg", "trace", "traceId", "begin", "pv_id", "sid", "seq", "domain", "flag" ], parseStatData = function(e) {
    var t = (e.key || "default").split("::");
    return t.length > 1 ? util.ext(e, {
        group: t[0],
        key: t[1]
    }) : util.ext(e, {
        group: "default_group",
        key: t[0]
    });
}, Reporter = function(e) {
    Base.call(this, e);
    var t;
    try {
        t = "object" == typeof performance ? performance.timing.fetchStart : Date.now();
    } catch (r) {
        t = Date.now();
    }
    return this._startTime = t, this;
};

Reporter.prototype = util.createObject(Base.prototype), util.ext(Base.dftCon, {
    startTime: null
}), util.ext(Reporter.prototype, {
    constructor: Reporter,
    _super: Base,
    sum: function(e, t, r) {
        try {
            var i = util.dealParam(e, t, 1);
            return this._lg("sum", parseStatData(i), r);
        } catch (a) {
            util.warn("[retcode] can not get parseStatData: " + a);
        }
    },
    avg: function(e, t, r) {
        try {
            var i = util.dealParam(e, t, 0);
            return this._lg("avg", parseStatData(i), r);
        } catch (a) {
            util.warn("[retcode] can not get parseStatData: " + a);
        }
    },
    percent: function(e, t, r, i) {
        try {
            return this._lg("percent", parseStatData({
                key: e,
                subkey: t,
                val: r || 0,
                begin: Date.now()
            }), i);
        } catch (a) {
            util.warn("[retcode] can not get parseStatData: " + a);
        }
    },
    msg: function(e, t) {
        if (e && !(e.length > 180)) return this.custom({
            msg: e
        }, t);
    },
    error: function(e, t) {
        if (!e) return util.warn("[retcode] invalid param e: " + e), this;
        1 === arguments.length ? ("string" == typeof e && (e = {
            message: e
        }, t = {}), "object" == typeof e && (t = e = e.error || e)) : ("string" == typeof e && (e = {
            message: e
        }), "object" != typeof t && (t = {}));
        var r = e.name || "CustomError", i = e.message || "", a = e.stack || "";
        t = t || {};
        var s = "object" == typeof location && "string" == typeof location.href && location.href.substring(0, 500) || "";
        if (util.checkSDKError(i, t.filename)) {
            var n = /^Script error\.?$/, o = e.msg || e.message;
            if (util.ignoreByRule(o, n) || util.ignoreByRule(util.decode(o), n)) return this;
            var u = {
                msg: util.selfErrKey,
                err: {
                    msg_raw: util.encode(e.msg || e.message)
                }
            };
            return this._self("error", u, 1);
        }
        for (var l = {
            begin: Date.now(),
            cate: r,
            msg: i && i.substring(0, 1e3),
            stack: a && a.substring(0, 1e3),
            file: util.removeUrlSearch(t.filename || ""),
            line: t.lineno || "",
            col: t.colno || "",
            err: {
                msg_raw: util.encode(i),
                stack_raw: util.encode(a)
            },
            dl: s
        }, c = [ "tag", "c1", "c2", "c3" ], p = 0; p < c.length; p++) {
            var g = c[p];
            t[g] && (l[g] = t[g]);
        }
        var f = (this.getConfig("ignore") || {}).ignoreErrors;
        return util.ignoreByRule(l.msg, f) || util.ignoreByRule(util.decode(l.msg), f) ? this : (this.beforeSend && this.beforeSend("error", l), 
        this._lg("error", l, 1));
    },
    behavior: function(e) {
        if (e) {
            var t = "object" == typeof e && e.behavior ? e : {
                behavior: e
            };
            return this.beforeSend && this.beforeSend("behavior", t), this._lg("behavior", t, 1);
        }
    },
    api: function(e, t, r, i, a, s, n, o, u, l, c, p) {
        if (!e) return util.warn("[retcode] api is null"), this;
        if (e = "string" == typeof e ? {
            api: e,
            success: t,
            time: r,
            code: i,
            msg: a,
            begin: s,
            traceId: n,
            pv_id: o,
            apiSnapshot: u,
            domain: l,
            flag: p
        } : util.sub(e, validApiKeys), !util.checkAPI(e.api, !0)) return this;
        e.code = e.code || "";
        var g = e.msg || "";
        if (g = "string" == typeof g ? g.substring(0, 1e3) : g, e.msg = g, e.success = e.success ? 1 : 0, 
        e.time = +e.time, e.begin = e.begin, e.traceId = e.traceId || "", e.pv_id = e.pv_id || "", 
        e.domain = e.domain || "", e.flag = e.flag, e.dl = "object" == typeof location && "string" == typeof location.href && location.href.substring(0, 500) || "", 
        e.success ? e.apiSnapshot && delete e.apiSnapshot : e.apiSnapshot = u, c && (e.traceOrigin = c), 
        !e.api || isNaN(e.time)) return util.warn("[retcode] invalid time or api"), this;
        var f = (this.getConfig("ignore") || {}).ignoreApis;
        return util.ignoreByRule(e.api, f) || util.ignoreByRule(util.decode(e.api), f) ? this : (this.beforeSend && this.beforeSend("api", e), 
        this._lg("api", e, e.success && this.getConfig("sample"), e.flag));
    },
    speed: function(e, t, r) {
        var i = this, a = this.getConfig("startTime") || this._startTime;
        return /^s(\d|1[0])$/.test(e) ? (t = "number" != typeof t ? Date.now() - a : t >= a ? t - a : t, 
        i.speedCache = i.speedCache || {}, i.speedCache[e] = t, i.speedCache.begin = a, 
        clearTimeout(i.speedTimmer), i.speedTimmer = setTimeout(function() {
            r || (i.speedCache.page = i.getPage(!0)), i._lg("speed", i.speedCache), i.speedCache = null;
        }, 5e3), i) : (util.warn("[retcode] invalid point: " + e), i);
    },
    performance: function(e) {
        if (e && "object" == typeof e && !this.hasSendPerf) {
            var t = {}, r = {}, i = this.getConfig("autoSendPerf");
            if (e.autoSend && i) return r = util.ext(this.perfData || {}, e), this.hasSendPerf = !0, 
            this._lg("perf", r, this.getConfig("sample"));
            if (e.autoSend && !i) return delete e.autoSend, this.perfData ? (r = util.ext(this.perfData || {}, e), 
            this.hasSendPerf = !0, this._lg("perf", r, this.getConfig("sample"))) : void (this.perfData = e);
            for (var a in e) (/^t([1-9]|1[0])$/.test(a) || "ctti" === a || "cfpt" === a) && (t[a] = e[a]);
            if (!0 === e.autoSend || !i && (i || this.perfData)) return !0 !== e.autoSend && !1 === i && this.perfData ? (t = util.ext(this.perfData || {}, t), 
            this.hasSendPerf = !0, this._lg("perf", t, this.getConfig("sample"))) : void 0;
            this.perfData = util.ext(this.perfData || {}, t);
        }
    },
    resource: function(e, t) {
        if (!e || !util.isPlainObject(e)) return util.warn("[arms] invalid param data: " + e), 
        this;
        var r = Object.keys(e), i = [ "begin", "dom", "load", "res", "dl" ], a = !1;
        for (var s in i) {
            if (r.indexOf(i[s]) < 0) {
                a = !0;
                break;
            }
        }
        if (a) return util.warn("[arms] lack param data: " + e), this;
        var n = {
            begin: e.begin || Date.now(),
            dom: e.dom || "",
            load: e.load || "",
            res: util.isArray(e.res) ? JSON.stringify(e.res) : JSON.stringify([]),
            dl: e.dl || ""
        };
        return this._lg("res", n, t);
    }
}), Reporter._super = Base, Reporter._root = Base, Base.Reporter = Reporter, module.exports = Reporter;